package com.yonyou.ucf.mdf.app.isvdxq.other.service;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yonyou.ucf.mdf.app.isvdxq.ReturnResult.DataResult;
import com.yonyou.ucf.mdf.app.isvdxq.common.ApiYon;
import com.yonyou.ucf.mdf.app.isvdxq.common.DxqConfig;
import com.yonyou.ucf.mdf.app.isvdxq.firstpart.appconfig.entity.AppconfigEntity;
import com.yonyou.ucf.mdf.app.isvdxq.other.entity.SuiteauthEntity;
import com.yonyou.ucf.mdf.app.isvdxq.other.entity.UserstaffEntity;
import com.yonyou.ucf.mdf.app.isvdxq.other.entity.WarehouseEntity;
import com.yonyou.ucf.mdf.app.isvdxq.other.model.*;
import com.yonyou.ucf.mdf.app.isvdxq.utils.*;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用友接口访问公用方法
 */
@Service
public class BaseService {
    private static final Logger logger = LoggerFactory.getLogger(BaseService.class);

    @Autowired
    private YmsPropertyUtil propertyUtil;

    @Autowired
    private MyTokenService myTokenService;

    @Autowired
    private TenantConfigService tenantConfigService;
    @Autowired
    private SuiteauthService suiteauthService;

    @Autowired
    private UserstaffService userstaffService;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private ApplicationContext applicationContext;

    /**
     * 设置默认租户
     * @param tenantId
     * @return
     */
    public AccessTokenResponse getAccessToken3(String tenantId) {
        if (StringUtils.isEmpty(tenantId)) {
            tenantId = DxqConfig.tenantId;
        }
        return myTokenService.getAccessToken3(tenantId);
    }

    /**
     * getGatewayUrl
     * @param tenantId
     * @return
     * @throws IOException
     */
    public String buildBusinessUrl(String tenantId) throws IOException {
        TenantConfig tenantConfig = tenantConfigService.getTenantConfig(tenantId);
        if (tenantConfig != null && !StringUtils.isEmpty(tenantConfig.getGatewayUrl())) return tenantConfig.getGatewayUrl();

        DcUrlResult dcUrl = myTokenService.getGateway(tenantId);
        return dcUrl.getGatewayUrl();
    }

    /**
     * getTokenUrl
     * @param tenantId
     * @return
     * @throws IOException
     */
    public String buildTokenUrl(String tenantId) throws IOException {
        TenantConfig tenantConfig = tenantConfigService.getTenantConfig(tenantId);
        if (tenantConfig != null && !StringUtils.isEmpty(tenantConfig.getTokenUrl())) return tenantConfig.getTokenUrl();

        DcUrlResult dcUrl = myTokenService.getGateway(tenantId);
        return dcUrl.getTokenUrl();
    }

    /**
     * 根据userId获取访问权限下的应用信息 不含ServiceCode
     *
     * @param access_token
     * @param tenantId
     * @param appCode
     * @return
     * @throws IOException
     */
    public String getApplicationId(String access_token, String tenantId, String appCode) throws IOException {
        String res = "";
        String gatewayUrl = buildBusinessUrl(tenantId);
//        String url = gatewayUrl + ApiYon.getAppId + "?access_token=" + access_token + "&appCode=" + appCode;
//        Request req = PostMan.getBuilder(url).get().build();
//        Call call = PostMan.getInstance().newCall(req);
//        Response response = call.execute();
//        String resString = response.body().string();
        Map<String, String> params = new HashMap<>();
        String requestUrl = gatewayUrl + ApiYon.getAppId +"?access_token=" + access_token;
        params.put("appCode", appCode);
        String resString = RequestTool.doGet(requestUrl, params);
        GenericResponse<ApplicationBean> responseObj = RequestTool.getBean(resString, new TypeReference<GenericResponse<ApplicationBean>>() {
        });

        if (responseObj.getCode().equals("200")) {
            ApplicationBean obj = responseObj.getData();
            res = obj.getApplicationId();
        }
        return res;
    }


    /**
     * 获取 ServiceCode
     * 暂未使用
     * @param yhtUserId
     * @param access_token
     * @return
     */
    public String getServiceCode(String yhtUserId, String access_token, String tenantId) throws IOException {
        String res = "";
        if (StringUtils.isEmpty(yhtUserId) || StringUtils.isEmpty(access_token)) return res;
        String gatewayUrl = buildBusinessUrl(tenantId);
//        String url = gatewayUrl + ApiYon.getServiceCode + "?access_token=" + access_token + "&userId=" + yhtUserId;
//        Request req = PostMan.getBuilder(url).get().build();
//        Call call = PostMan.getInstance().newCall(req);
//        Response response = call.execute();
//        String resString = response.body().string();
        Map<String, String> params = new HashMap<>();
        String requestUrl = gatewayUrl + ApiYon.getServiceCode +"?access_token=" + access_token;
        params.put("userId", yhtUserId);
        String resString = RequestTool.doGet(requestUrl, params);
        GenericResponse<List<ApplicationBean>> responseObj = RequestTool.getBean(resString, new TypeReference<GenericResponse<List<ApplicationBean>>>() {
        });

        if (responseObj.getCode().equals("200")) {
            List<ApplicationBean> appList = responseObj.getData();
            List<ApplicationBean> objList = appList.stream()
                    .filter(it -> it.getServiceCode().equals(DxqConfig.serviceCode))
                    .collect(Collectors.toList());
            if (objList.size() == 0) return res;
            res = objList.get(0).getServiceCode();
        }
        return res;
    }

    /**
     * 获取自建服务列表
     * https://dbox.diwork.com/iuap-api-gateway/yonbip/uspace/app/list_by_app_code?access_token=41a214043a9649d3b664bd5773768b84&appCode=Idx3
     *
     * @param gatewayUrl
     * @param access_token
     * @return
     * @throws IOException
     */
    public String getServiceCode2(String gatewayUrl, String access_token) throws IOException {
        String res = "";
        if (StringUtils.isEmpty(gatewayUrl) || StringUtils.isEmpty(access_token)) return res;
//        String url = gatewayUrl + ApiYon.getAppcode + "?access_token=" + access_token + "&appCode=" + DxqConfig.applicationCode;
//        Request req = PostMan.getBuilder(url).get().build();
//        Call call = PostMan.getInstance().newCall(req);
//        Response response = call.execute();
//        String resString = response.body().string();
        Map<String, String> params = new HashMap<>();
        String requestUrl = gatewayUrl + ApiYon.getAppcode +"?access_token=" + access_token;
        params.put("appCode", DxqConfig.applicationCode);
        String resString = RequestTool.doGet(requestUrl, params);
        GenericResponse<List<ApplicationBean>> responseObj = RequestTool.getBean(resString, new TypeReference<GenericResponse<List<ApplicationBean>>>() {
        });

        if (responseObj.getCode().equals("200")) {
            List<ApplicationBean> appList = responseObj.getData();
            List<ApplicationBean> objList = appList.stream()
                    .filter(it -> it.getServiceCode().equals(DxqConfig.serviceCode))
                    .collect(Collectors.toList());
            if (objList.size() == 0) return res;
            res = objList.get(0).getServiceCode();
        }
        return res;
    }

    /**
     * 用户查询
     * @param access_token
     * @param tenantId
     * @param userName 目前支持手机号 检索关键词：手机号、邮箱、账号
     * @return
     */
    @SneakyThrows
    public UserBean getUserInfo(String access_token, String tenantId, String userName){
        // 本地部门权限查询
        if (DxqConfig.DXQ_sandbox.equals(DxqConfig.active)){
            UserBean userBean = new UserBean();
            userBean.setUserMobile(userName);
            userBean.setTenant_id(tenantId);
            UserstaffEntity userstaffEntity = userstaffService.SelectByMobile(tenantId, userName);
            userBean.setUserId(userstaffEntity.getYhtUserId());
            userBean.setUserName(userstaffEntity.getUserName());
            userBean.setUser_id(String.valueOf(userstaffEntity.getId()));
            userBean.setName(userstaffEntity.getTrueName());

            return userBean;
        }
        // 远程获取用友数据
        AccessTokenResponse resToken = this.getAccessToken3(tenantId);
        if (StringUtils.isEmpty(access_token)) {
            access_token = resToken.getAccessToken();
        }
        if (StringUtils.isBlank(access_token)) {
            return null;
        }
        //{"index": 1, "size": 1000, "searchcode":mobile}
        String gatewayUrl = this.buildBusinessUrl(tenantId);
        String url = gatewayUrl + ApiYon.getUserInfo + "?access_token=" + access_token;

        Map<String, Object> params_req = new HashMap<>();
        params_req.put("index", "1");
        params_req.put("size", "10");
        params_req.put("searchcode", userName);
        Map<String, String> params_header = new HashMap<>();
        params_header.put("noCipherFlag", "true");
        String resString = RequestTool.doPost(url, params_req, params_header);
        GenericResponse<UserPage<UserBean>> responseObj = RequestTool.getBean(resString,
                new TypeReference<GenericResponse<UserPage<UserBean>>>() {
                });
        if (!responseObj.getCode().equals("200")) {
            return null;
        }

        UserPage<UserBean> userList = responseObj.getData();

        if (userList.getContent() == null || userList.getContent().size() == 0) {
            return null;
        }
        UserBean uInfo = userList.getContent().get(0);

        return uInfo;
    }
    /**
     * 获取授权组织Id列表 主组织权限查询
     * 在线用友获取
     * @param yhtUserId
     * @param tenantId
     * @return
     */
    @SneakyThrows
    public List<String> getOrgListByUserId(String yhtUserId, String tenantId) {
        List<String> res = new ArrayList<>();
        if (StringUtils.isEmpty(yhtUserId) || StringUtils.isEmpty(tenantId)) {
            return res;
        }
        // 本地部门权限查询
//        if (DxqConfig.DXQ_sandbox.equals(DxqConfig.active)) {
//            DataParam<DepartmentUserEntity> param = new DataParam<>();
//            param.setUserId(Long.parseLong(yhtUserId));
//            param.setTenantId(tenantId);
//            List<DepartmentUserEntity> arr = departmentUserService.SelectListEntity(param);
//            return arr.stream().map(it -> it.getFkDepartmentid().toString()).collect(Collectors.toList());
//        }

        AccessTokenResponse MyToken = this.getAccessToken3(tenantId);
        String access_token = MyToken.getAccessToken();
        String gatewayUrl = buildBusinessUrl(tenantId);
//        String serviceCode = getServiceCode2(gatewayUrl, access_token);
//        if (StringUtils.isEmpty(serviceCode)) return res;
        // okhttp3
//            String url = gatewayUrl + ApiYon.getPermission + "?access_token=" + access_token;
//            MediaType JSON = MediaType.parse("application/json; charset=utf-8");
//            JSONObject json = new JSONObject();
//            json.put("userId", yhtUserId);
//            json.put("serviceCode", serviceCode);
//            json.put("tenantId", tenantId);
//
//            RequestBody bodyData = RequestBody.create(JSON, json.toJSONString());
//            final OkHttpClient okHttpClient = new OkHttpClient();
//            final Request req = new Request.Builder().url(url).post(bodyData).build();
//            Call call = okHttpClient.newCall(req);
//            Response response = call.execute();
//            String resString = response.body().string();

        // 方案二
        Map<String, Object> params = new HashMap<>();
        String requestUrl = gatewayUrl + ApiYon.getPermission + "?access_token=" + access_token;
        params.put("userId", yhtUserId);
        params.put("serviceCode", DxqConfig.serviceCode);
        params.put("tenantId", tenantId);
        String resString = RequestTool.doPost(requestUrl, params);
        GenericResponse<List<String>> responseObj = RequestTool.getBean(resString, new TypeReference<GenericResponse<List<String>>>() {
        });

        if (responseObj.getCode().equals("200")) {
            res = responseObj.getData();
        } else {
            System.out.println(resString);
        }
        return res;
    }

    public List<String> getOrgList(Map<String, Object> reqParams, String org_id, String tenant_id) {
        String strOrgids = (String) reqParams.get("orgids");
        List<String> strList = new ArrayList<>();
        if (!org_id.equals("null") && !StringUtils.isEmpty(org_id)) strList.add(org_id);
        else {
            if (!StringUtils.isEmpty(strOrgids)) {
                strList.addAll(new ArrayList<>(Arrays.asList(strOrgids.split(","))));
            } else {
                String userId = (String) reqParams.get("userId");
                List<String> myList = getOrgListByUserId(userId, tenant_id);
                strList.addAll(myList);
            }
        }
        return strList;
    }

    /**
     * 获取当前用户仓库权限
     * @return
     */
    public List<String> getWarehouseIds(String userId, String tenantId){
        List<String> strList = new ArrayList<>();
        List<String> orgList = getOrgListByUserId(userId, tenantId);
        List<WarehouseEntity> warehouseList = warehouseService.SelectByOrgIds(orgList, tenantId);
        strList = warehouseList.stream().map(warehouseEntity -> warehouseEntity.getId().toString()).collect(Collectors.toList());
        return strList;
    }


    /**
     * 获取租户配置
     *
     * @param request
     */
    public TenantConfig GetTenantConfig(HttpServletRequest request) {
        try {
            String tenantId = getTenantId(request);
            if (StringUtils.isEmpty(tenantId)) return null;
            //私有Token方案 默认赋值 德鑫TenantId
            String tenantId_Now = StringUtils.isEmpty(tenantId) ? DxqConfig.tenantId : tenantId;
            //TenantConfig缓存
            TenantConfig tenantConfig = tenantConfigService.getTenantConfig(tenantId_Now);
            if (tenantConfig == null) {
                tenantConfig = new TenantConfig();
                tenantConfig.setTenantId_DXQ(tenantId_Now);
                String gatewayUrl = buildBusinessUrl(tenantId_Now);
                String tokenUrl = buildTokenUrl(tenantId_Now);
                tenantConfig.setTokenUrl(tokenUrl);
                tenantConfig.setGatewayUrl(gatewayUrl);
                //缓存不存在时写入缓存
                tenantConfigService.saveTenantConfig(tenantConfig);
            }
            return tenantConfig;
        } catch (Exception ex) {
            logger.error("[HeaderInterceptor-TenantConfig缓存]" + ex.getMessage());
        }
        return null;
    }

    public void TenantConfigOnload(HttpServletRequest request) {
        try {
            String userId = RequestTool.getHeaderAndParameter(request, DxqConfig.DXQ_userId);
            TenantConfig tenantConfig = GetTenantConfig(request);
            TenantConfigInit(tenantConfig, userId);
        } catch (Exception ex) {
            logger.error("[BaseService-TenantConfigOnload]" + ex.getMessage());
        }
    }

    /**
     * 初始化租户信息
     */
    public void TenantConfigInit(TenantConfig tenantConfig, String userId) {
        try {
            if (tenantConfig==null || StringUtils.isEmpty(tenantConfig.getTenantId_DXQ())) return;
            String tenantId = tenantConfig.getTenantId_DXQ();
            TenantConfigAdd(tenantId, userId, "ticket", DxqConfig.appKey, DxqConfig.appSecret);
            TenantConfigAdd(tenantId, userId, "ticket", DxqConfig.suiteKey, DxqConfig.suiteSecret);
        } catch (Exception ex) {
            logger.error("[BaseService-TenantConfig初始化]" + ex.getMessage());
        }
    }

    /**
     * 订阅租户记录
     * 涉及：数据中心、accesstoken、租户、本地租户缓存列表
     * @param tenantId
     * @param userId
     */
    public void TenantConfigAdd(String tenantId, String userId, String ticket, String suiteKey, String suiteSecret) {
        try {
            if (StringUtils.isEmpty(tenantId)) return;
            // 获取租户名称
            String tenantName = "";
            String todayString = MyTool.GenerateTime("yyyy-MM-dd");
            String gatewayUrl = buildBusinessUrl(tenantId);
            String tokenUrl = buildTokenUrl(tenantId);
            SuiteauthEntity suiteauthEntity = suiteauthService.CheckEntityByKey(tenantId, suiteKey);
            if (suiteauthEntity == null) {
                suiteauthEntity = new SuiteauthEntity();
                // 写入Token
                suiteauthEntity.setSuiteKey(suiteKey);
                suiteauthEntity.setTenant_id(tenantId);
                suiteauthEntity.setGatewayUrl(gatewayUrl);
                suiteauthEntity.setTokenUrl(tokenUrl);
                suiteauthEntity.setDxqToken(MyTool.GenerateDxqToken(tenantId));
                suiteauthEntity.setUserid(userId);
                suiteauthEntity.setEditTime(todayString);
                suiteauthEntity.setTicket(ticket);
                suiteauthEntity.setSuiteSecret(suiteSecret);
                String tenantInfo = myTokenService.getTenantById(tenantId);
                if (StringUtils.isNotBlank(tenantInfo)) {
                    JSONObject object = JSONObject.parseObject(tenantInfo);
                    tenantName = object.getJSONObject("tenant").get("tenantName").toString();
                }
                suiteauthEntity.setTenantName(tenantName);

                AccessTokenResponse resToken = this.getAccessToken3(tenantId);
                suiteauthEntity.setAccessToken(resToken.getAccessToken());
                suiteauthEntity.setExpireAt(String.valueOf(resToken.getExpire()));
                suiteauthService.InsertEntity(suiteauthEntity);
            }
            // 更新兼容历史数据
            else {
                suiteauthEntity.setUserid(userId);
                suiteauthEntity.setTicket(ticket);
                suiteauthEntity.setSuiteSecret(suiteSecret);
                suiteauthService.UpdateEntity(suiteauthEntity);
            }
        } catch (Exception ex) {
            logger.error("[BaseService-TenantConfig初始化]" + ex.getMessage());
        }
    }

    /**
     * AppconfigInit 更新或新增
     * @param tenantId
     * @param userId
     */
    public void AppconfigInit(String tenantId, String userId) {
        List<AppconfigEntity> addEntity = new ArrayList<>();
        String apiUrl = DxqConfig.myBaseUrl;
        apiUrl = String.format("%s%s", apiUrl, DxqConfig.pre_apiUrl);
        String domainKey = DxqConfig.applicationCode;
        Integer appType = 0;
        AppconfigEntity appconfigEntity = suiteauthService.SelectLastEntity(tenantId, domainKey, appType);
        if (appconfigEntity == null) {
            appconfigEntity = new AppconfigEntity();
            appconfigEntity.setId(Long.parseLong(MyTool.getRandomId()));
            appconfigEntity.setCreateTime(MyTool.GenerateTime());
            appconfigEntity.setCreator(userId);
            appconfigEntity.setVersion(2);
            appconfigEntity.setTenant_id(tenantId);
            appconfigEntity.setAppType(appType.intValue());
            appconfigEntity.setAppcode(DxqConfig.applicationCode);
            appconfigEntity.setApplicationid(DxqConfig.domainKey);
            appconfigEntity.setLocalservurl(apiUrl);
            appconfigEntity.setModifyTime(appconfigEntity.getCreateTime());
        }
        appconfigEntity.setStatus(1);
        appconfigEntity.setDr(0);
        if (appconfigEntity.getLocalservurl() != null && !appconfigEntity.getLocalservurl().equals(apiUrl)) {
            appconfigEntity.setLocalservurl(apiUrl);
        }
        addEntity.add(appconfigEntity);
        suiteauthService.InsertBatch(addEntity);
    }

    /**
     * 免登获取用户信息
     * ===============================================================
     * 协同手机号接触加密设置
     * 免登接口 ，后面拼接 flag: 表示返回手机号信息
     * https://api.diwork.com/open-auth/selfAppAuth/getBaseInfoByCode?access_token=xxx&code=xx
     * x&flag=true
     * 其他接口
     * 返回的手机号信息是加密的，如果需要解密需要在 HTTP 的 header 中添加
     * noCipherFlag=true
     * 注意：该设置涉及到客户信息的保密性，需要征得客户的同意才可以发送给伙伴，伙伴不可私下传递
     * ===============================================================
     * 原生APP友户通统一认证集成方案
     * 接口描述	根据授权code获取用户信息，包括用户所属租户列表
     * 接口地址	https://api.diwork.com/open-auth/freelogin/getBaseInfoByCode
     * 更新为网关地址
     * @param authorizeCode
     * @return
     */

    public DataResult GetBaseInfo(String authorizeCode) {
        DataResult dataResult = new DataResult(1, "查询成功");
        try {
            Map<String, String> params = new HashMap<>();
            params.put("code", authorizeCode);
            // 通用code获取用户信息 /yonbip/digitalModel/userCode/getByCode?access_token=&code=
            // 协同免登 /yonbip/uspace/freelogin/base_info_by_code?access_token=&code=
            String requestUrl = DxqConfig.openApiUrlGateway + ApiYon.getBaseInfoByCode;
            String response = RequestTool.doGet(requestUrl, params);
            logger.info(requestUrl + "\n[GetBaseInfo]" + response);
            JSONObject jsonObject = JSONObject.parseObject(response);
            if (jsonObject.getString("code").equals("00000")) {
                dataResult.setData(jsonObject.getJSONObject("data"));
            } else {
                dataResult = new DataResult(0, jsonObject.getString("message"));
            }
            return dataResult;
        } catch (Exception e) {
            dataResult = new DataResult(0, "查询失败！");
            logger.info("[GetBaseInfo]" + JSONObject.toJSONString(e));
        }
        return dataResult;
    }

    /**
     * 历史方案
     * @param authorizeCode
     * @param suiteKey
     * @param suiteSecret
     * @return
     */
    public DataResult GetBaseInfo(String authorizeCode, String suiteKey, String suiteSecret) {
        DataResult dataResult = new DataResult(1, "查询成功");
        try {
            Map<String, String> params = new HashMap<>();
            params.put("suiteKey", suiteKey);
            params.put("code", authorizeCode);
            params.put("timestamp", String.valueOf(MyTool.timeGen()));
            // 计算签名
            String signature = SignHelper.sign(params, suiteSecret);
            params.put("signature", signature);
            // 通用code获取用户信息 /yonbip/digitalModel/userCode/getByCode?access_token=&code=
            // 协同免登 /yonbip/uspace/freelogin/base_info_by_code?access_token=&code=
            String requestUrl = DxqConfig.datacenterDomain + ApiYon.getBaseinfo;
            String response = RequestTool.doGet(requestUrl, params);
            logger.info(requestUrl + "\n[GetBaseInfo]" + response);
            JSONObject jsonObject = JSONObject.parseObject(response);
            if (jsonObject.getString("code").equals("00000")) {
                dataResult.setData(jsonObject.getString("data"));
            } else {
                dataResult = new DataResult(0, response);
            }
            return dataResult;
        } catch (Exception e) {
            dataResult = new DataResult(0, "查询失败！");
            logger.info("[GetBaseInfo]" + JSONObject.toJSONString(e));
        }
        return dataResult;
    }

    /**
     * UpdateToken 更新Token
     * @param tenantId
     * @param accessToken
     * @param yhtUserId
     * @param expireAt
     */
    public void UpdateToken(String tenantId, String yhtUserId, String accessToken, String expireAt) {
        suiteauthService.UpdateToken(tenantId, yhtUserId, accessToken, expireAt);
    }

    /**
     * 功能页获取 TenantId
     * @param request
     * @return
     */
    public String getTenantId(HttpServletRequest request) {
        String tenantId = RequestTool.getHeaderAndParameter(request, DxqConfig.DXQ_tenantId);
        if (StringUtils.isEmpty(tenantId)) tenantId = myTokenService.getTenantId();
        return tenantId;
    }

    /**
     * 获取用户 yht_access_token
     * @param request
     * @return
     */
    public String getYhtAccessToken(HttpServletRequest request){
        String yht_access_token = RequestTool.getHeaderAndParameter(request, "yht_access_token");
        if(StringUtils.isEmpty(yht_access_token)) {
            yht_access_token = RequestTool.findCookieValue(request.getCookies(), "yht_access_token");
        }
        return yht_access_token;
    }

    //baseService.UpdateToken(tenantId_Now, userId, resToken.getAccessToken(), String.valueOf(resToken.getExpire()));

}
